# from sample-appengine copy image-sharing

from google.appengine.ext import db
from google.appengine.api import images

import random
from datetime import datetime

class Album(db.Model):
    """
    An album is an organizational unit for pictures.
    """
    name = db.StringProperty()
    cover = db.ReferenceProperty()
    creator = db.UserProperty()
    created_date = db.DateTimeProperty(auto_now_add=True)

class Picture(db.Model):
    """
    Storage for a picture and its associated metadata.
    """
    submitter = db.UserProperty()
    submitted_date = db.DateTimeProperty(auto_now_add=True)
    title = db.StringProperty()
    caption = db.StringProperty(multiline=True)
    album = db.ReferenceProperty(Album, collection_name='pictures')
    tags = db.StringListProperty()
    data = db.BlobProperty()            # the original data
    large_data = db.BlobProperty()      # resized to 1440x1080
    thumbnail_data = db.BlobProperty()  # thumbnail 60x100
    middle_data = db.BlobProperty()     # middle size 960x720

    @property
    def etag(self):
        import hashlib
        return hashlib.sha1(self.data).hexdigest()

    def resize(self):
        """
        thumbnail, middle, large and the original
        """
        pic = self
        pic.large_data = None
        pic.middle_data = None
        pic.thumbnail_data = None

        img = images.Image(pic.data)
        width, height = 1440, 1080
        if img.width >width or img.height >height:
            img.resize(width, height)
            pic.large_data = img.execute_transforms(images.JPEG)

        width, height = 960, 720
        if img.width >width or img.height >height:
            img.resize(width, height)
            pic.middle_data = img.execute_transforms(images.JPEG)

        width, height = 60, 100
        if img.width >width or img.height >height:
            img.resize(width, height)
            pic.thumbnail_data = img.execute_transforms(images.JPEG)

        pic.put()

    @classmethod
    def random(cls):
        """
        select a picture randomly. have no idea about what a true random number is.
        """
        pics = Picture.all()
        total_pics = pics.count()
        if total_pics == 0: return
        if total_pics == 1: return pics[0]
        return pics[random.randint(0, total_pics-1)]

    # pass in the file handle (request.FILES.get('handle'))
    @classmethod
    def process_upload(cls, handle, **kargs):
        """
        process an uppload request, user may upload things other than pictures, too large pictures
        or pictures we can not proceed.
        """
        common_formats = ['image/jpeg',
                          'image/png',
                          'image/x-png',
                          'image/gif',
                          'image/x-ms-bmp',
                          'image/tiff']
        if handle.content_type not in common_formats:
            raise images.NotImageError
        if handle.size >1000000:
            raise images.LargeImageError
        title, extension = handle.name.rsplit('.', 1)
        if extension.lower() not in ['jpeg', 'jpg', 'jpe', 'png', 'gif', 'bmp', 'tiff', 'ico']:
            title += '.%s' % extension
        try:
            img_data = handle.read()
            img = images.Image(img_data)
            img.im_feeling_lucky()
            jpg_data = img.execute_transforms(images.JPEG)
        except:
            raise
        if kargs.get('album') and kargs.get('user'):
            user = kargs.get('user')
            album = kargs.get('album')
            pic_key = Picture(submitter=user,
                              title=title,
                              caption='',
                              album=album,
                              data=jpg_data,).put()
            pic = Picture.get(pic_key)
            pic.resize()
            return pic
        elif kargs.get('picture'):
            pic = kargs.get('picture')
            pic.data = jpg_data
            pic.submitted_date = datetime.now()
            pic.put()
            pic.resize()
            return pic
        else:                           # wrong argument
            raise KeyError

